package com.jdy.singleton.lazy;

/**
 * 懒汉式 双重检查锁单例
 * <p>
 * 为了保证单例的线程安全，使用双重加锁的方式
 * 问题：加锁所造成的性能问题
 */
public class LazyDoubleCheckSingleton {

    /**
     * 类加载时不初始化实例
     * <p>
     * volatile 可以防止指令重排序问题
     */
    private volatile static LazyDoubleCheckSingleton INSTANCE;

    /**
     * 私有化构造方法
     */
    private LazyDoubleCheckSingleton() {
    }

    /**
     * 等到调用时初始化单例实例
     * <p>
     * 提供全局访问点
     * <p>
     * 如果没有 synchronized关键字，容易出现线程安全问题，因此需要添加synchronized进行同步
     *
     * @return 单例对象
     */
    public static LazyDoubleCheckSingleton getInstance() {
        //这里需保证只有一个实例
        if (INSTANCE == null)
            synchronized (LazyDoubleCheckSingleton.class) {
                if (INSTANCE == null)//防止重复创建
                    INSTANCE = new LazyDoubleCheckSingleton();
                /*
                 * CPU执行时会转换成JVM指令执行
                 *
                 * 1.分配内存给这个对象
                 * 2.初始化对象
                 * 3.将初始化后的对象和内存地址建立关联，赋值
                 * 4.用户初次访问
                 *
                 */
                //指令重排序问题, 所以会在单例对象添加volatile修饰
            }
        return INSTANCE;
    }
}
